#pragma once
#include "Comm.h"

namespace COMM
{
	class COMM_API Atom
	{
	public:
		// returns the initial value.
		static int Exchange(volatile int& target, int val);
		static int CompareExchange(volatile int& target, int val, int valcompare);
		static void* ExchangePointer(void* volatile& target, void* val);
		static void* CompareExchangePointer(void* volatile& target, void* val, void* valcompare);
		// returns the initial value.
		static int Add(volatile int& target, int val);
		// returns the initial value.
		static int Sub(volatile int& target, int val);

		// 64bit version.(Minimum supported Windows is Vista)
		//
		// returns the initial value.
		static long long Exchange(volatile long long& target, long long val);
		static long long CompareExchange(volatile long long& target, long long val, long long valcompare);
		// returns the initial value.
		static long long Add(volatile long long& target, long long val);
		// returns the initial value.
		static long long Sub(volatile long long& target, long long val);
	};

	template<class T>
	class AtomInteger
	{
		MYLIB_NONCOPIED_CLASS(AtomInteger);
	private:
		struct dummy {void nonnull() {};};
		typedef void (dummy::*safebool)();
	public:
		explicit AtomInteger(T val=0):m_val(val){}
		const volatile T& get() const{ return m_val;}
		operator T() const { return m_val; }
		T setif(int val, int valcompare) { return Atom::CompareExchange(m_val, val, valcompare);}

		// returns the initial value.
		T operator=(T val){ return Atom::Exchange(m_val,val);}
		// returns the initial value.
		T operator+=(T val){ return Atom::Add(m_val,val);}
		// returns the initial value.
		T operator-=(T val){ return Atom::Sub(m_val,val);}
		// returns the value after add.
		T operator++(){ return (Atom::Add(m_val,(T)1)+1);} //++i;
		// returns the value after sub.
		T operator--(){ return (Atom::Sub(m_val,(T)1)-1);} //--i;
		// returns the initial value.
		T operator++(int){ return Atom::Add(m_val,(T)1);} //i++;
		// returns the initial value.
		T operator--(int){ return Atom::Sub(m_val,(T)1);} //i--;

		bool operator==(T val) const { return (m_val==val); }
		bool operator!=(T val) const { return (m_val!=val); }
		bool operator>=(T val) const { return (m_val>=val); }
		bool operator<=(T val) const { return (m_val<=val); }
		bool operator>(T val) const { return (m_val>val); }
		bool operator<(T val) const { return (m_val<val); }

		// convert to void* for boolean compare.
		operator safebool() const{ return (m_val ? (&dummy::nonnull) : 0);}

	private:
		volatile T m_val;
	};

#ifdef COMM_MSVC
	template class COMM_API AtomInteger<int>;
	template class COMM_API AtomInteger<long long>;
#endif
	typedef AtomInteger<int> AtomInt;
	typedef AtomInteger<long long> AtomInt64;
}





